package org.dromara.app.controller.admin;

import cn.dev33.satoken.annotation.SaCheckPermission;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.dromara.app.domain.bo.AppRoleBo;
import org.dromara.app.domain.vo.AppRoleVo;
import org.dromara.app.service.AppRoleService;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.validate.AddGroup;
import org.dromara.common.core.validate.EditGroup;
import org.dromara.common.excel.utils.ExcelUtil;
import org.dromara.common.log.annotation.Log;
import org.dromara.common.log.enums.BusinessType;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseController;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 管理端角色信息
 *
 * @author ruoyi
 */
@Tag(name = "管理端角色管理", description = "管理端角色信息管理接口")
@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/admin/role")
public class AdminRoleController extends BaseController {

    private final AppRoleService appRoleService;

    /**
     * 查询管理端角色信息列表
     */
    @Operation(summary = "查询角色列表", description = "分页查询管理端角色信息列表")
    @SaCheckPermission("admin:role:list")
    @GetMapping("/list")
    public TableDataInfo<AppRoleVo> list(@Parameter(description = "角色查询条件") AppRoleBo bo, 
                                         @Parameter(description = "分页参数") PageQuery pageQuery) {
        return appRoleService.queryPageList(bo, pageQuery);
    }

    /**
     * 导出管理端角色信息列表
     */
    @Operation(summary = "导出角色列表", description = "导出管理端角色信息到Excel")
    @SaCheckPermission("admin:role:export")
    @Log(title = "管理端角色信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(@Parameter(description = "角色查询条件") AppRoleBo bo, 
                       @Parameter(description = "响应对象") HttpServletResponse response) {
        List<AppRoleVo> list = appRoleService.queryList(bo);
        ExcelUtil.exportExcel(list, "管理端角色信息", AppRoleVo.class, response);
    }

    /**
     * 获取管理端角色信息详细信息
     */
    @Operation(summary = "获取角色详情", description = "根据角色ID获取详细信息")
    @SaCheckPermission("admin:role:query")
    @GetMapping("/{roleId}")
    public R<AppRoleVo> getInfo(@Parameter(description = "角色ID", required = true) 
                                @NotNull(message = "主键不能为空")
                                @PathVariable Long roleId) {
        return R.ok(appRoleService.queryById(roleId));
    }

    /**
     * 新增管理端角色信息
     */
    @Operation(summary = "新增角色", description = "新增管理端角色信息")
    @SaCheckPermission("admin:role:add")
    @Log(title = "管理端角色信息", businessType = BusinessType.INSERT)
    @PostMapping()
    public R<Void> add(@Parameter(description = "角色信息", required = true) 
                       @Validated(AddGroup.class) @RequestBody AppRoleBo bo) {
        return toAjax(appRoleService.insertByBo(bo));
    }

    /**
     * 修改管理端角色信息
     */
    @Operation(summary = "修改角色", description = "修改管理端角色信息")
    @SaCheckPermission("admin:role:edit")
    @Log(title = "管理端角色信息", businessType = BusinessType.UPDATE)
    @PutMapping()
    public R<Void> edit(@Parameter(description = "角色信息", required = true) 
                        @Validated(EditGroup.class) @RequestBody AppRoleBo bo) {
        return toAjax(appRoleService.updateByBo(bo));
    }

    /**
     * 删除管理端角色信息
     */
    @Operation(summary = "删除角色", description = "批量删除管理端角色信息")
    @SaCheckPermission("admin:role:remove")
    @Log(title = "管理端角色信息", businessType = BusinessType.DELETE)
    @DeleteMapping("/{roleIds}")
    public R<Void> remove(@Parameter(description = "角色ID数组", required = true) 
                          @NotEmpty(message = "主键不能为空")
                          @PathVariable Long[] roleIds) {
        return toAjax(appRoleService.deleteWithValidByIds(List.of(roleIds), true));
    }

    /**
     * 获取角色选择框列表
     */
    @Operation(summary = "获取角色选项", description = "获取角色选择框列表")
    @SaCheckPermission("admin:role:query")
    @GetMapping("/optionselect")
    public R<List<AppRoleVo>> optionselect() {
        List<AppRoleVo> roles = appRoleService.queryList(new AppRoleBo());
        return R.ok(roles);
    }

    /**
     * 查询已分配用户角色列表
     */
    @Operation(summary = "查询已分配用户", description = "查询已分配用户角色列表")
    @SaCheckPermission("admin:role:list")
    @GetMapping("/authUser/allocatedList")
    public TableDataInfo<AppRoleVo> allocatedList(@Parameter(description = "角色查询条件") AppRoleBo bo, 
                                                   @Parameter(description = "分页参数") PageQuery pageQuery) {
        return appRoleService.queryPageList(bo, pageQuery);
    }

    /**
     * 查询未分配用户角色列表
     */
    @Operation(summary = "查询未分配用户", description = "查询未分配用户角色列表")
    @SaCheckPermission("admin:role:list")
    @GetMapping("/authUser/unallocatedList")
    public TableDataInfo<AppRoleVo> unallocatedList(@Parameter(description = "角色查询条件") AppRoleBo bo, 
                                                     @Parameter(description = "分页参数") PageQuery pageQuery) {
        return appRoleService.queryPageList(bo, pageQuery);
    }

    /**
     * 取消授权用户
     */
    @Operation(summary = "取消授权用户", description = "批量取消用户角色授权")
    @SaCheckPermission("admin:role:edit")
    @Log(title = "管理端角色信息", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/cancelAll")
    public R<Void> cancelAuthUserAll(@Parameter(description = "角色ID", required = true) Long roleId, 
                                      @Parameter(description = "用户ID数组", required = true) Long[] userIds) {
        return toAjax(appRoleService.deleteAuthUsers(roleId, userIds));
    }

    /**
     * 批量选择用户授权
     */
    @Operation(summary = "批量授权用户", description = "批量选择用户进行角色授权")
    @SaCheckPermission("admin:role:edit")
    @Log(title = "管理端角色信息", businessType = BusinessType.GRANT)
    @PutMapping("/authUser/selectAll")
    public R<Void> selectAuthUserAll(@Parameter(description = "角色ID", required = true) Long roleId, 
                                      @Parameter(description = "用户ID数组", required = true) Long[] userIds) {
        return toAjax(appRoleService.insertAuthUsers(roleId, userIds));
    }

}